package com.geezdata.cps.sdk3rd.youzan;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.geezdata.cps.base.enums.ErrorCode;
import com.geezdata.cps.base.response.BaseResponse;
import com.geezdata.cps.base.utils.HttpClientUtil;
import com.geezdata.cps.base.utils.MapUtil;
import com.geezdata.cps.sdk3rd.youzan.request.YouzanRequest;
import com.geezdata.cps.sdk3rd.youzan.response.YouzanResult;


public class YouzanDefaultClient implements YouzanClient {
    private String serverUrl; // 要调用的服务的url（serverUrl后面要加上时间戳参数，避免请求缓存的影响）
    private String appKey; // appkey 应用的唯一标识，对应一个业务组
    private String appSecret; // appSecret 该业务组的授权密钥

    private static Logger logger = LoggerFactory.getLogger(YouzanDefaultClient.class);


    public YouzanDefaultClient(String serverUrl, String appKey, String appSecret) {
        this.appKey = appKey;
        this.appSecret = appSecret;
        this.serverUrl = serverUrl;
    }

    public <T extends YouzanResult> BaseResponse<T> execute(YouzanRequest<T> request) {
     // 1、检查serverUrl、appkey、appsert参数是否有空
        if( StringUtils.isEmpty(serverUrl) || StringUtils.isEmpty(appKey) 
                || StringUtils.isEmpty(appSecret)) {
        	return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), ErrorCode.INVALID_PARAMS.getDesc());
        }      
        
        // 2、Request及自身参数检查
        if(request == null) {
        	return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), ErrorCode.INVALID_PARAMS.getDesc());
        }
       
        // 3、初始化data和msgId
        Map<String, Object> paramsMap =  request.getAppParams();
        if( paramsMap == null ||  paramsMap.isEmpty()) {
        	return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), ErrorCode.INVALID_PARAMS.getDesc());
        }
     
        // 4、发送报文并获取响应的报文串
        String rspStr = null;
        try {
            rspStr = HttpClientUtil.post(serverUrl, prepareHttpParams(request));
        } catch (Exception e) {
        	return BaseResponse.error(ErrorCode.HTTP_EXCEPTION.getCode(), e.getMessage());
        } 
        
        // 5、将返回封装成对应的Response
        if(StringUtils.isEmpty(rspStr)){
            logger.info("resp str is empty");
            return BaseResponse.error(ErrorCode.HTTP_EXCEPTION.getCode(), "resp str is empty");
        }

        JSONObject jsonObject = JSONObject.parseObject(rspStr);
        if (jsonObject.containsKey("error_response")) {
        	return BaseResponse.error(ErrorCode.HTTP_EXCEPTION.getCode(), 
        			jsonObject.getJSONObject("error_response").toString());
        } 
        
        T youzanResult = (T) JSONObject.toJavaObject(jsonObject, request.getResponseClass());
        return (BaseResponse<T>) BaseResponse.success(youzanResult);
    }
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private Map<String, Object> prepareHttpParams(YouzanRequest youzanRequest) {
    	Map<String, Object> httpParams = new HashMap<String, Object>();
        httpParams.put("app_id", appKey);
        httpParams.put("app_secret", appSecret);
        httpParams.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        httpParams.put("format", "json");
        httpParams.put("method", youzanRequest.getMethodName());
        httpParams.put("v", "1.0");

        // 获取应用级别参数
		Map<String, Object> appParams = youzanRequest.getAppParams();
        Iterator<String> it = appParams.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            Object value = appParams.get(key);
            httpParams.put(key, value);
        }
        
        //去除空参数
        MapUtil.removeNull(httpParams);
        
        // 获得sign
        httpParams.put("sign", createSign(httpParams));
        return httpParams;
    }

    private String createSign(Map<String, Object> requestParamsMap) {
        Object[] keyArray = requestParamsMap.keySet().toArray();
        List<String> keyList = new ArrayList<String>();
        for (int i = 0; i < keyArray.length; i++) {
            keyList.add((String) keyArray[i]);
        }
        Collections.sort(keyList);
        String signContent = appSecret;

        for (String key : keyList) {
            signContent += (key + requestParamsMap.get(key).toString());
        }
        signContent += appSecret;
        return hash(signContent);
    }

    private static String hash(String signContent) {
        String hashResult = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(signContent.getBytes("UTF-8"));
            byte byteData[] = md.digest();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < byteData.length; i++) {
                sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
            }
            hashResult = sb.toString().toLowerCase();
        } catch (NoSuchAlgorithmException e) {
        } catch (UnsupportedEncodingException e) {
            logger.error("", e);
        }

        return hashResult;
    }
}
